package web_api

import (
	"encoding/json"
	"fmt"
	"github.com/gin-gonic/gin"
	"github.com/jinzhu/gorm"
	"net/http"
	"platon-tools/go-service/common/constant"
	"platon-tools/go-service/common/util"
	go_logger "platon-tools/go-service/go-logger"
	"platon-tools/go-service/module"
	"platon-tools/go-service/module/model"
	"strconv"
	"time"
)

type StakingTotalResponse struct {
	TotalStaking   string `json:"total_staking"`
	TotalAuthorize string `json:"total_authorize"`
	TotalBenefit   string `json:"total_benefit"`
}

// 所有节点汇总
func (api *HttpApi) StakingTotal(c *gin.Context) {

	var err error

	userId, exist := c.Get("login_id")
	if !exist || userId == "" {
		c.JSON(http.StatusOK, util.FailResponse(constant.ERROR_CODE_1103, constant.ERROR_MESSAGE_1103))
		return
	}

	r := api.service.ModuleByName("MYSQLDB")
	if db, ok := r.(*module.MysqlDB); ok {
		var result StakingTotalResponse

		var nodes []*model.SysNodeContract

		var user model.SysUser
		err = db.Table(model.SysUserTable).Where(map[string]interface{}{"id": userId}).Find(&user).Error
		if err != nil {
			go_logger.Logger.Error(err.Error())
			c.JSON(http.StatusOK, util.FailResponse(constant.ERROR_CODE_1001, constant.ERROR_MESSAGE_1001))
			return
		}

		var role model.SysRole
		err = db.Table(model.SysRoleTable).Where(map[string]interface{}{"id": user.RoleId}).Find(&role).Error
		if err != nil {
			go_logger.Logger.Error(err.Error())
			c.JSON(http.StatusOK, util.FailResponse(constant.ERROR_CODE_1001, constant.ERROR_MESSAGE_1001))
			return
		}

		selectDb := db.Table(model.SysNodeContractTable).Where(" node_primary_id in (?)", role.GetNodePerm())
		err = selectDb.Find(&nodes).Error
		if err != nil {
			go_logger.Logger.Error(err.Error())
			c.JSON(http.StatusOK, util.FailResponse(constant.ERROR_CODE_1001, constant.ERROR_MESSAGE_1001))
			return
		}

		var staking, authorize, benefit float64
		for _, node := range nodes {
			staking += node.StakingSum
			authorize += node.DelegationSum
			benefit += node.TotalReward
		}
		result.TotalStaking = fmt.Sprintf("%.2f", staking)
		result.TotalAuthorize = fmt.Sprintf("%.2f", authorize)
		result.TotalBenefit = fmt.Sprintf("%.8f", benefit)

		c.JSON(http.StatusOK, util.SuccessResponse(result))
		return
	}
}

type IndexTotalResponse struct {
	TotalBalance string `json:"total_balance"`
	FlowAmount   int    `json:"flow_amount"`
	FlowTotal    int    `json:"flow_total"`
	NextPeriod   int    `json:"next_period"`
	IngMotion    int    `json:"ing_motion"`
	TotalMotion  int    `json:"total_motion"`
}

// 首页概览
func (api *HttpApi) IndexTotal(c *gin.Context) {

	var err error

	userId, exist := c.Get("login_id")
	if !exist || userId == "" {
		c.JSON(http.StatusOK, util.FailResponse(constant.ERROR_CODE_1103, constant.ERROR_MESSAGE_1103))
		return
	}

	r := api.service.ModuleByName("MYSQLDB")
	if db, ok := r.(*module.MysqlDB); ok {
		var result IndexTotalResponse

		var nodes []*model.SysNodeContract

		// 管理员有最大的权限，直接看管理员
		var role model.SysRole
		err = db.Table(model.SysRoleTable).Where(map[string]interface{}{"id": 1}).Find(&role).Error
		if err != nil {
			go_logger.Logger.Error(err.Error())
			c.JSON(http.StatusOK, util.FailResponse(constant.ERROR_CODE_1001, constant.ERROR_MESSAGE_1001))
			return
		}

		selectDb := db.Table(model.SysNodeContractTable).Where(" node_primary_id in (?)", role.GetNodePerm())
		err = selectDb.Find(&nodes).Error
		if err != nil {
			go_logger.Logger.Error(err.Error())
			c.JSON(http.StatusOK, util.FailResponse(constant.ERROR_CODE_1001, constant.ERROR_MESSAGE_1001))
			return
		}

		type NextPeriod struct {
			NextPeriod   int     `json:"next_period"`
			TotalBalance float64 `json:"total_balance"`
		}
		var next NextPeriod
		err = db.Raw("select max(next_period) as next_period from node_contract").Scan(&next).Error
		if err != nil {
			go_logger.Logger.Error(err.Error())
			c.JSON(http.StatusOK, util.FailResponse(constant.ERROR_CODE_1001, constant.ERROR_MESSAGE_1001))
			return
		}

		err = db.Raw("select sum(total_balance) as total_balance from node_contract").Scan(&next).Error
		if err != nil {
			go_logger.Logger.Error(err.Error())
			c.JSON(http.StatusOK, util.FailResponse(constant.ERROR_CODE_1001, constant.ERROR_MESSAGE_1001))
			return
		}

		result.TotalBalance = fmt.Sprintf("%.8f", next.TotalBalance)
		result.FlowAmount = 97113248
		result.FlowTotal = 104728273
		result.IngMotion = 21
		result.TotalMotion = 1568
		result.NextPeriod = next.NextPeriod

		c.JSON(http.StatusOK, util.SuccessResponse(result))
		return
	}
}

type NodeStakingDetailResponse struct {
	DelegationReward     string `json:"delegation_reward"`       // 累计委托奖励
	NodeNotReceiveReward string `json:"node_not_receive_reward"` // 待领取委托奖励
	PropertySum          string `json:"property_sum"`            // 总资产折合
	TotalReward          string `json:"total_reward"`            // 累计收益
	TodayBenefit         string `json:"today_benefit"`           // 今日收益
	YesterdayBenefit     string `json:"yesterday_benefit"`       // 昨日收益
	StakingAddr          string `json:"staking_addr"`            // 质押地址
	StakingAddrAccount   string `json:"staking_addr_account"`    // 质押地址余额
	StakingReward        string `json:"staking_reward"`          // 质押奖励
	BonusRatio           string `json:"bonus_ratio"`             // 分红比例
	MiningReward         string `json:"mining_reward"`           // 出块奖励
	BenefitAddr          string `json:"benefit_addr"`            // 收益地址
	BenefitAddrAccount   string `json:"benefit_addr_account"`    // 收益地址余额
	BlockingNode         string `json:"blocking_node"`           // 当前出块节点
	NextPeriod           uint64 `json:"next_period"`             // 下个结算周期
}

// 单个节点汇总
func (api *HttpApi) NodeStakingDetail(c *gin.Context) {

	var err error

	userId, exist := c.Get("login_id")
	if !exist || userId == "" {
		c.JSON(http.StatusOK, util.FailResponse(constant.ERROR_CODE_1103, constant.ERROR_MESSAGE_1103))
		return
	}

	nodeId := c.Query("node_id")
	if nodeId == "" {
		c.JSON(http.StatusOK, util.FailResponse(constant.ERROR_CODE_1003, "请输入node_id"))
		return
	}

	r := api.service.ModuleByName("MYSQLDB")
	if db, ok := r.(*module.MysqlDB); ok {
		var result NodeStakingDetailResponse

		var nodeContract model.SysNodeContract
		err = db.Table(model.SysNodeContractTable).Where(map[string]interface{}{"node_primary_id": nodeId}).Find(&nodeContract).Error
		if err != nil {
			go_logger.Logger.Error(err.Error())
			c.JSON(http.StatusOK, util.FailResponse(constant.ERROR_CODE_1001, constant.ERROR_MESSAGE_1001))
			return
		}

		today := time.Now().Format(constant.DATE_DAY_FORMAT)
		yesterday := time.Now().AddDate(0, 0, -1).Format(constant.DATE_DAY_FORMAT)

		type TodayYesterday struct {
			TodayBenifit     uint64 `json:"today_benifit"`
			YesterdayBenifit uint64 `json:"yesterday_benifit"`
		}
		// 今日收益，昨日收益
		var todayReward TodayYesterday
		err = db.Raw("select sum(benefit_sum) from node_contract_history where node_primary_id = " + nodeId + " and create_time >= '" + today + "'").First(&todayReward).Error
		if err != nil {
			go_logger.Logger.Error(err.Error())
			c.JSON(http.StatusOK, util.FailResponse(constant.ERROR_CODE_1001, constant.ERROR_MESSAGE_1001))
			return
		}

		var yesterdayReward TodayYesterday
		err = db.Raw("select sum(benefit_sum) from node_contract_history where node_primary_id = " + nodeId + " and create_time >= '" + yesterday + "' and create_time < '" + today + "'").First(&yesterdayReward).Error
		if err != nil {
			go_logger.Logger.Error(err.Error())
			c.JSON(http.StatusOK, util.FailResponse(constant.ERROR_CODE_1001, constant.ERROR_MESSAGE_1001))
			return
		}

		ratioFloat, _ := util.ToFloat64(nodeContract.BonusRatio)

		result.TodayBenefit = fmt.Sprintf("%.8f", util.ToLat(todayReward.TodayBenifit))
		result.YesterdayBenefit = fmt.Sprintf("%.8f", util.ToLat(yesterdayReward.YesterdayBenifit))
		result.StakingReward = fmt.Sprintf("%.8f", nodeContract.StakingReward)
		result.BonusRatio = fmt.Sprintf("%.2f", ratioFloat/100)
		result.DelegationReward = fmt.Sprintf("%.8f", nodeContract.DelegationReward)
		result.MiningReward = fmt.Sprintf("%.8f", nodeContract.MiningReward)
		result.NodeNotReceiveReward = fmt.Sprintf("%.8f", nodeContract.DelegationNotReceive)
		result.TotalReward = fmt.Sprintf("%.8f", nodeContract.TotalReward)
		result.StakingAddr = nodeContract.StakingAddr
		result.StakingAddrAccount = fmt.Sprintf("%.8f", nodeContract.StakingAddrAccount)
		result.BenefitAddr = nodeContract.BenefitAddr
		result.BenefitAddrAccount = fmt.Sprintf("%.8f", nodeContract.BenefitAddrAccount)
		result.BlockingNode = nodeContract.CurrentBlockingNode
		result.NextPeriod = nodeContract.NextPeriod

		c.JSON(http.StatusOK, util.SuccessResponse(result))
		return
	}
}

type NodeListRequest struct {
	Params   string `form:"params" uri:"params" json:"params"`
	Page     int    `form:"page" uri:"page" json:"page" binding:"required"`
	PageSize int    `form:"page_size" uri:"page_size" json:"page_size" binding:"required"`
	OrderBy  string `form:"order_by" uri:"order_by" json:"order_by"`
}

type NodeListResponse struct {
	Id             int    `json:"id"`
	NodeId         string `json:"node_id"`
	NodeName       string `json:"node_name"`
	ChainId        int    `json:"chain_id"`
	ChainName      string `json:"chain_name"`
	CPU            int    `json:"cpu"`
	Memory         int    `json:"memory"`
	Disk           int    `json:"disk"`
	LogLevel       string `json:"log_level"`
	SyncMode       string `json:"log_level"`
	RpcAddr        string `json:"rpc_addr"`
	P2PPort        int    `json:"p2p_port"`
	RpcPort        int    `json:"rpc_port"`
	StakingSum     string `json:"staking_sum"`
	DelegationSum  string `json:"delegation_sum"`
	TotalReward    string `json:"total_reward"`
	Status         int    `json:"status"`
	CreateUserName string `json:"create_user_name"`
	CreateTime     string `json:"create_time"`
	UpdateUserName string `json:"update_user_name"`
	UpdateTime     string `json:"update_time"`
}

// 节点列表
func (api *HttpApi) NodeList(c *gin.Context) {

	var err error
	var result []*NodeListResponse

	userId, exist := c.Get("login_id")
	if !exist || userId == "" {
		c.JSON(http.StatusOK, util.FailResponse(constant.ERROR_CODE_1103, constant.ERROR_MESSAGE_1103))
		return
	}

	pageStr := c.Query("page")
	pageSizeStr := c.Query("page_size")
	param := c.Query("params")
	chainId := c.Query("chainId")
	orderBy := c.Query("order_by")
	order := c.Query("order")

	page, err := strconv.Atoi(pageStr)
	if err != nil {
		go_logger.Logger.Error(err.Error())
		c.JSON(http.StatusOK, util.FailResponse(constant.ERROR_CODE_1003, "page 应为数字"))
		return
	}

	pageSize, err := strconv.Atoi(pageSizeStr)
	if err != nil {
		go_logger.Logger.Error(err.Error())
		c.JSON(http.StatusOK, util.FailResponse(constant.ERROR_CODE_1003, "pageSize 应为数字"))
		return
	}

	r := api.service.ModuleByName("MYSQLDB")
	if db, ok := r.(*module.MysqlDB); ok {
		var nodes []*model.SysNode

		var user model.SysUser
		err = db.Table(model.SysUserTable).Where(map[string]interface{}{"id": userId}).Find(&user).Error
		if err != nil {
			go_logger.Logger.Error(err.Error())
			c.JSON(http.StatusOK, util.FailResponse(constant.ERROR_CODE_1001, constant.ERROR_MESSAGE_1001))
			return
		}

		var role model.SysRole
		err = db.Table(model.SysRoleTable).Where(map[string]interface{}{"id": user.RoleId}).Find(&role).Error
		if err != nil {
			go_logger.Logger.Error(err.Error())
			c.JSON(http.StatusOK, util.FailResponse(constant.ERROR_CODE_1001, constant.ERROR_MESSAGE_1001))
			return
		}

		var count int
		var countDb = db.Table(model.SysNodeTable).Where(" id in (?)", role.GetNodePerm())
		if len(param) > 0 {
			countDb = countDb.Where("node_name like ?", "%"+param+"%")
		}
		if len(chainId) > 0 {
			countDb = countDb.Where("chain_id = ?", chainId)
		}
		err = countDb.Count(&count).Error
		if err != nil {
			go_logger.Logger.Error(err.Error())
			c.JSON(http.StatusOK, util.FailResponse(constant.ERROR_CODE_1001, constant.ERROR_MESSAGE_1001))
			return
		}

		if count > 0 {
			selectDb := db.Table(model.SysNodeTable).Joins("join node_contract on node_contract.node_primary_id = sys_node.id").Where(" sys_node.id in (?)", role.GetNodePerm())
			if len(param) > 0 {
				selectDb = selectDb.Where("sys_node.node_name like ?", "%"+param+"%")
			}
			if len(chainId) > 0 {
				selectDb = selectDb.Where("sys_node.chain_id = ?", chainId)
			}
			if len(orderBy) > 0 {
				selectDb = selectDb.Order("node_contract." + orderBy + " " + order)
			} else {
				selectDb = selectDb.Order("sys_node.update_time desc")
			}
			err = selectDb.Limit(pageSize).Offset((page - 1) * pageSize).Find(&nodes).Error
			if err != nil {
				go_logger.Logger.Error(err.Error())
				c.JSON(http.StatusOK, util.FailResponse(constant.ERROR_CODE_1001, constant.ERROR_MESSAGE_1001))
				return
			}

			for _, node := range nodes {

				var nodeContract model.SysNodeContract
				err = db.Table(model.SysNodeContractTable).Where(" node_primary_id = ?", node.Id).Find(&nodeContract).Error
				if err != nil {
					go_logger.Logger.Error(err.Error())
					c.JSON(http.StatusOK, util.FailResponse(constant.ERROR_CODE_1001, constant.ERROR_MESSAGE_1001))
					return
				}

				item := &NodeListResponse{}
				item.Id = node.Id
				item.NodeId = node.NodeId
				item.NodeName = node.NodeName
				item.ChainId = node.ChainId
				item.ChainName = node.ChainName
				item.Status = node.Status
				item.LogLevel = node.LogLevel
				item.SyncMode = node.SyncMode
				item.CPU = node.CPU
				item.Memory = node.Memory
				item.Disk = node.Disk
				item.StakingSum = fmt.Sprintf("%.2f", nodeContract.StakingSum)
				item.DelegationSum = fmt.Sprintf("%.2f", nodeContract.DelegationSum)
				item.TotalReward = fmt.Sprintf("%.8f", nodeContract.TotalReward)
				item.CreateUserName = node.CreateUserName
				item.UpdateUserName = node.UpdateUserName
				item.CreateTime = node.CreateTime.Format(constant.DATE_FORMAT)
				item.UpdateTime = node.UpdateTime.Format(constant.DATE_FORMAT)

				result = append(result, item)
			}
		}

		c.JSON(http.StatusOK, util.SuccessResponse(map[string]interface{}{
			"list":  result,
			"count": count,
		}))
		return
	}
}

// 节点详情
func (api *HttpApi) NodeDetail(c *gin.Context) {

	var err error
	var result []*NodeListResponse

	nodeId := c.Query("node_id")

	r := api.service.ModuleByName("MYSQLDB")
	if db, ok := r.(*module.MysqlDB); ok {
		var node model.SysNode

		err = db.Table(model.SysNodeTable).Where(map[string]interface{}{
			"id": nodeId,
		}).Find(&node).Error
		if err != nil {
			go_logger.Logger.Error(err.Error())
			c.JSON(http.StatusOK, util.FailResponse(constant.ERROR_CODE_1001, constant.ERROR_MESSAGE_1001))
			return
		}

		var nodeContract model.SysNodeContract
		err = db.Table(model.SysNodeContractTable).Where(" node_primary_id = ?", node.Id).Find(&nodeContract).Error
		if err != nil {
			go_logger.Logger.Error(err.Error())
			c.JSON(http.StatusOK, util.FailResponse(constant.ERROR_CODE_1001, constant.ERROR_MESSAGE_1001))
			return
		}

		item := &NodeListResponse{}
		item.NodeName = node.NodeName
		item.ChainId = node.ChainId
		item.ChainName = node.ChainName
		item.Status = node.Status
		item.LogLevel = node.LogLevel
		item.SyncMode = node.SyncMode
		item.CPU = node.CPU
		item.Memory = node.Memory
		item.Disk = node.Disk
		item.StakingSum = fmt.Sprintf("%.2f", nodeContract.StakingSum)
		item.DelegationSum = fmt.Sprintf("%.2f", nodeContract.DelegationSum)
		item.TotalReward = fmt.Sprintf("%.8f", nodeContract.TotalReward)
		item.CreateUserName = node.CreateUserName
		item.UpdateUserName = node.UpdateUserName
		item.CreateTime = node.CreateTime.Format(constant.DATE_FORMAT)
		item.UpdateTime = node.UpdateTime.Format(constant.DATE_FORMAT)

		result = append(result, item)

		c.JSON(http.StatusOK, util.SuccessResponse(item))
		return
	}
}

type AuthTreeItem struct {
	ChainId   int        `json:"id"`
	ChainName string     `json:"name"`
	Nodes     []NodeItem `json:"nodes"`
}

type NodeItem struct {
	Id       int    `json:"id"`
	ChainId  int    `json:"chain_id"`
	NodeName string `json:"name"`
}

// 节点树
func (api *HttpApi) NodeTree(c *gin.Context) {

	var err error

	r := api.service.ModuleByName("MYSQLDB")
	if db, ok := r.(*module.MysqlDB); ok {
		var nodes []*model.SysNode
		where := map[string]interface{}{
			"status": constant.USER_STATUS_USING,
		}
		err = db.Table(model.SysNodeTable).Where(where).Find(&nodes).Error
		if err != nil {
			c.JSON(http.StatusOK, util.FailResponse(constant.ERROR_CODE_1100, constant.ERROR_MESSAGE_1100))
			return
		}

		authTree := BuildTree(nodes)

		c.JSON(http.StatusOK, util.SuccessResponse(authTree))
		return
	}
}

// 构建节点树
func BuildTree(nodes []*model.SysNode) []AuthTreeItem {
	authTree := []AuthTreeItem{}
	// 存chainId和index的关系
	index := map[int]int{}
	for _, node := range nodes {

		if i, ok := index[node.ChainId]; ok {
			authTree[i].Nodes = append(authTree[i].Nodes, NodeItem{node.Id, node.ChainId, node.NodeName})
			continue
		}

		item := AuthTreeItem{
			ChainId:   node.ChainId,
			ChainName: node.ChainName,
			Nodes:     []NodeItem{{node.Id, node.ChainId, node.NodeName}},
		}
		index[node.ChainId] = len(authTree)
		authTree = append(authTree, item)
	}
	return authTree
}

type AddNodeRequest struct {
	NodeName  string `json:"node_name" binding:"required"`
	ChainId   int    `json:"chain_id" binding:"required"`
	ChainName string `json:"chain_name" binding:"required"`
	CPU       int    `json:"cpu"`
	Memory    int    `json:"memory"`
	Disk      int    `json:"disk"`
	LogLevel  string `json:"log_level"`
	SyncMode  string `json:"log_level"`
	RpcAddr   string `json:"rpc_addr"`
	P2PPort   int    `json:"p2p_port"`
	RpcPort   int    `json:"rpc_port"`
}

// 新增节点
func (api *HttpApi) AddNode(c *gin.Context) {

	var err error

	userId, exist := c.Get("login_id")
	if !exist || userId == "" {
		c.JSON(http.StatusOK, util.FailResponse(constant.ERROR_CODE_1103, constant.ERROR_MESSAGE_1103))
		return
	}
	userName, exist := c.Get("login_name")
	if !exist || userName == "" {
		c.JSON(http.StatusOK, util.FailResponse(constant.ERROR_CODE_1103, constant.ERROR_MESSAGE_1103))
		return
	}

	var param AddNodeRequest
	if err := c.ShouldBindJSON(&param); err != nil {
		go_logger.Logger.Error(err.Error())
		c.JSON(http.StatusOK, util.FailResponse(constant.ERROR_CODE_1002, constant.ERROR_MESSAGE_1002))
		return
	}

	r := api.service.ModuleByName("MYSQLDB")
	if db, ok := r.(*module.MysqlDB); ok {
		var node model.SysNode

		node.NodeName = param.NodeName
		node.ChainId = param.ChainId
		node.ChainName = param.ChainName
		node.CPU = param.CPU
		node.Memory = param.Memory
		node.Disk = param.Disk
		node.LogLevel = param.LogLevel
		node.SyncMode = param.SyncMode
		node.Status = constant.NODE_STATUS_USING
		node.CreateUserName = util.ToString(userName)
		node.CreateTime = time.Now()
		node.UpdateUserName = util.ToString(userName)
		node.UpdateTime = time.Now()

		err = db.Table(model.SysNodeTable).Save(&node).Error
		if err != nil {
			go_logger.Logger.Error(err.Error())
			c.JSON(http.StatusOK, util.FailResponse(constant.ERROR_CODE_1001, constant.ERROR_MESSAGE_1001))
			return
		}

		// 新节点权限要给到管理员
		var manager model.SysRole
		err = db.Table(model.SysRoleTable).Where(map[string]interface{}{
			"id":        1,
			"role_name": "管理员",
		}).Find(&manager).Error
		if err != nil {
			go_logger.Logger.Error(err.Error())
			c.JSON(http.StatusOK, util.FailResponse(constant.ERROR_CODE_1001, constant.ERROR_MESSAGE_1001))
			return
		}

		perm := manager.GetNodePerm()
		perm = append(perm, node.Id)
		permByte, _ := json.Marshal(perm)

		manager.NodePerm = string(permByte)
		manager.UpdateTime = time.Now()
		manager.UpdateUserName = util.ToString(userName)
		err = db.Table(model.SysRoleTable).Save(&manager).Error
		if err != nil {
			go_logger.Logger.Error(err.Error())
			c.JSON(http.StatusOK, util.FailResponse(constant.ERROR_CODE_1001, constant.ERROR_MESSAGE_1001))
			return
		}

		// TODO 请求谷歌云，创建新节点

		c.JSON(http.StatusOK, util.SuccessResponse(nil))
		return
	}
}

type EditNodeRequest struct {
	NodeId    int    `json:"node_id" binding:"required"`
	NodeName  string `json:"node_name" binding:"required"`
	ChainId   int    `json:"chain_id" binding:"required"`
	ChainName string `json:"chain_name" binding:"required"`
	CPU       int    `json:"cpu"`
	Memory    int    `json:"memory"`
	Disk      int    `json:"disk"`
	Status    int    `json:"status"`
	LogLevel  string `json:"log_level"`
	SyncMode  string `json:"sync_mode"`
	RpcAddr   string `json:"rpc_addr"`
	P2PPort   int    `json:"p2p_port"`
	RpcPort   int    `json:"rpc_port"`
}

// 编辑节点
func (api *HttpApi) EditNode(c *gin.Context) {

	var err error

	userId, exist := c.Get("login_id")
	if !exist || userId == "" {
		c.JSON(http.StatusOK, util.FailResponse(constant.ERROR_CODE_1103, constant.ERROR_MESSAGE_1103))
		return
	}
	userName, exist := c.Get("login_name")
	if !exist || userName == "" {
		c.JSON(http.StatusOK, util.FailResponse(constant.ERROR_CODE_1103, constant.ERROR_MESSAGE_1103))
		return
	}

	var param EditNodeRequest
	if err := c.ShouldBindJSON(&param); err != nil {
		go_logger.Logger.Error(err.Error())
		c.JSON(http.StatusOK, util.FailResponse(constant.ERROR_CODE_1002, constant.ERROR_MESSAGE_1002))
		return
	}

	r := api.service.ModuleByName("MYSQLDB")
	if db, ok := r.(*module.MysqlDB); ok {
		var node model.SysNode
		where := map[string]interface{}{
			"id": param.NodeId,
		}
		err = db.Table(model.SysNodeTable).Where(where).First(&node).Error
		if err != nil {
			go_logger.Logger.Error(err.Error())
			c.JSON(http.StatusOK, util.FailResponse(constant.ERROR_CODE_1001, constant.ERROR_MESSAGE_1001))
			return
		}

		node.NodeName = param.NodeName
		node.ChainId = param.ChainId
		node.ChainName = param.ChainName
		node.CPU = param.CPU
		node.Memory = param.Memory
		node.Disk = param.Disk
		node.LogLevel = param.LogLevel
		node.SyncMode = param.SyncMode
		node.RpcPort = param.RpcPort
		node.P2PPort = param.P2PPort
		node.RpcAddr = param.RpcAddr
		node.Status = param.Status
		node.UpdateUserName = util.ToString(userName)
		node.UpdateTime = time.Now()

		err = db.Table(model.SysNodeTable).Save(&node).Error
		if err != nil {
			go_logger.Logger.Error(err.Error())
			c.JSON(http.StatusOK, util.FailResponse(constant.ERROR_CODE_1002, constant.ERROR_MESSAGE_1002))
			return
		}

		c.JSON(http.StatusOK, util.SuccessResponse(nil))
		return
	}
}

// 删除节点
func (api *HttpApi) DeleteNode(c *gin.Context) {
	userId, exist := c.Get("login_id")
	if !exist || userId == "" {
		c.JSON(http.StatusOK, util.FailResponse(constant.ERROR_CODE_1103, constant.ERROR_MESSAGE_1103))
		return
	}
	userName, exist := c.Get("login_name")
	if !exist || userName == "" {
		c.JSON(http.StatusOK, util.FailResponse(constant.ERROR_CODE_1103, constant.ERROR_MESSAGE_1103))
		return
	}

	nodeId := c.Query("node_id")

	r := api.service.ModuleByName("MYSQLDB")
	if db, ok := r.(*module.MysqlDB); ok {
		var node model.SysNode
		where := map[string]interface{}{
			"id":     nodeId,
			"status": constant.NODE_STATUS_USING,
		}
		err := db.Table(model.SysNodeTable).Where(where).First(&node).Error
		if err != nil {
			go_logger.Logger.Error(err.Error())
			c.JSON(http.StatusOK, util.FailResponse(constant.ERROR_CODE_1001, constant.ERROR_MESSAGE_1001))
			return
		}

		node.Status = constant.NODE_STATUS_DELETE
		node.UpdateTime = time.Now()
		node.UpdateUserName = util.ToString(userName)

		err = db.Table(model.SysNodeTable).Save(&node).Error
		if err != nil {
			go_logger.Logger.Error(err.Error())
			c.JSON(http.StatusOK, util.FailResponse(constant.ERROR_CODE_1002, constant.ERROR_MESSAGE_1002))
			return
		}

		c.JSON(http.StatusOK, util.SuccessResponse(nil))
		return
	}
}

// 谷歌云回调
func (api *HttpApi) GoogleNode(c *gin.Context) {

	nodePrimaryIdStr := c.Query("node_primary_id")
	nodeId := c.Query("node_id")
	nodeName := c.Query("node_name")

	nodePrimaryId, err := strconv.Atoi(nodePrimaryIdStr)
	if err != nil {
		go_logger.Logger.Error(err.Error())
		c.JSON(http.StatusOK, util.FailResponse(constant.ERROR_CODE_1003, "nodePrimaryId 应该是一个数字"))
		return
	}

	r := api.service.ModuleByName("MYSQLDB")
	if db, ok := r.(*module.MysqlDB); ok {
		var node model.SysNode
		where := map[string]interface{}{
			"id": nodePrimaryId,
		}
		err = db.Table(model.SysNodeTable).Where(where).First(&node).Error
		if err != nil {
			go_logger.Logger.Error(err.Error())
			c.JSON(http.StatusOK, util.FailResponse(constant.ERROR_CODE_1001, constant.ERROR_MESSAGE_1001))
			return
		}

		node.NodeId = nodeId
		node.NodeName = nodeName
		node.Status = constant.NODE_STATUS_DELETE
		node.UpdateTime = time.Now()
		err = db.Table(model.SysNodeTable).Save(&node).Error
		if err != nil {
			go_logger.Logger.Error(err.Error())
			c.JSON(http.StatusOK, util.FailResponse(constant.ERROR_CODE_1002, constant.ERROR_MESSAGE_1002))
			return
		}

		// 更新node_contract
		var nodeContract model.SysNodeContract
		where = map[string]interface{}{
			"node_primary_id": nodePrimaryId,
		}
		err = db.Table(model.SysNodeContractTable).Where(where).First(&nodeContract).Error
		if err != nil && err != gorm.ErrRecordNotFound {
			go_logger.Logger.Error(err.Error())
			c.JSON(http.StatusOK, util.FailResponse(constant.ERROR_CODE_1001, constant.ERROR_MESSAGE_1001))
			return
		}
		if nodeContract.Id == 0 {
			nodeContract.CreateTime = time.Now()
		}

		nodeContract.NodePrimaryId = nodePrimaryId
		nodeContract.NodeId = nodeId
		nodeContract.NodeName = nodeName
		nodeContract.UpdateTime = time.Now()
		nodeContract.Status = constant.NODE_STATUS_USING

		err = db.Table(model.SysNodeContractTable).Save(&nodeContract).Error
		if err != nil {
			go_logger.Logger.Error(err.Error())
			c.JSON(http.StatusOK, util.FailResponse(constant.ERROR_CODE_1002, constant.ERROR_MESSAGE_1002))
			return
		}

		// 更新node_monitor
		var nodeMonitor model.SysNodeMonitor
		where = map[string]interface{}{
			"node_primary_id": nodePrimaryId,
		}
		err = db.Table(model.SysNodeMonitorTable).Where(where).First(&nodeMonitor).Error
		if err != nil && err != gorm.ErrRecordNotFound {
			go_logger.Logger.Error(err.Error())
			c.JSON(http.StatusOK, util.FailResponse(constant.ERROR_CODE_1001, constant.ERROR_MESSAGE_1001))
			return
		}
		if nodeMonitor.Id == 0 {
			nodeMonitor.CreateTime = time.Now()
		}

		nodeMonitor.NodePrimaryId = nodePrimaryId
		nodeMonitor.NodeId = nodeId
		nodeMonitor.NodeName = nodeName
		nodeMonitor.UpdateTime = time.Now()
		nodeMonitor.NodeStatus = constant.NODE_STATUS_USING

		err = db.Table(model.SysNodeMonitorTable).Save(&nodeMonitor).Error
		if err != nil {
			go_logger.Logger.Error(err.Error())
			c.JSON(http.StatusOK, util.FailResponse(constant.ERROR_CODE_1002, constant.ERROR_MESSAGE_1002))
			return
		}

		c.JSON(http.StatusOK, util.SuccessResponse(nil))
		return
	}
}
